package com.soul.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import com.soul.common.bean.vo.MenuTreeVo;
import com.soul.common.exception.BaseException;
import com.soul.common.service.BaseService;
import com.soul.common.utils.TreeUtil;
import com.soul.sys.bean.dto.MenuSearchDto;
import com.soul.sys.bean.dto.menu.MenuAddDto;
import com.soul.sys.bean.dto.menu.MenuUpdateDto;
import com.soul.sys.bean.po.MenuPo;
import com.soul.sys.bean.vo.MenuVo;
import com.soul.sys.bean.vo.RouteVo;
import com.soul.sys.mapper.MenuMapper;
import com.soul.sys.service.MenuService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 菜单 服务实现类
 * </p>
 *
 * @author sws
 * @since 2023-09-01 22:40:38
 */
@Service
public class MenuServiceImpl extends BaseService<MenuMapper, MenuPo> implements MenuService {

    @Override
    public List<MenuTreeVo> queryMenuTree(MenuSearchDto searchForm) {
        List<MenuTreeVo> treeVos = new ArrayList<>( );
        List<MenuPo> menuPos = this.list();
        if (menuPos != null){
            for (MenuPo menuPo : menuPos) {
                MenuTreeVo treeVo = new MenuTreeVo();
                BeanUtils.copyProperties(menuPo,treeVo);
                treeVos.add(treeVo);
            }
            treeVos = TreeUtil.buildTree(treeVos, 0L);
        }
        return treeVos;
    }

    /**
     * 新增菜单
     * @param menuAddDto
     */
    @Override
    public void addMenu(MenuAddDto menuAddDto) {
        MenuPo menuPo = new MenuPo();
        BeanUtil.copyProperties(menuAddDto,menuPo);
        // 简码
        String shortCode = menuAddDto.getShortCode();
        String menuCode = shortCode;
        // 父节点Id
        Long parentId = menuAddDto.getParentId();
        if (!ObjectUtil.isEmpty(parentId) && parentId != 0L){
            // 父节点菜单存在时
            MenuPo parentMenu = this.getById(parentId);
            if (ObjectUtil.isNotEmpty(parentMenu)){
                String menuCodeParent = parentMenu.getMenuCode();
                menuCode = menuCodeParent.concat("-").concat(shortCode);
            }
        }else {
            menuPo.setParentId(0L);
        }
        menuPo.setUrl(menuAddDto.getComponent());
        if (menuAddDto.getComponent().equals("/")){
            menuPo.setComponent("Layout");
        }
        menuPo.setMenuCode(menuCode);
        this.save(menuPo);
    }

    @Override
    public void updateMenu(MenuUpdateDto menuUpdateDto){
        // 查询当前节点数据
        MenuPo menuPo = this.getById(menuUpdateDto.getId());
        if (ObjectUtil.isNotEmpty(menuPo)){
            throw new BaseException("选中的数据不存在");
        }
        // 父节点
        Long parentId = menuPo.getParentId();
        if (ObjectUtil.equal(menuUpdateDto.getParentId(),menuPo.getId())){
            throw new BaseException("上级不能是自己！");
        }
        if (menuUpdateDto.getParentId() != null && !ObjectUtil.equal(menuUpdateDto.getParentId(),parentId)){
            // 修改上级目录
            if (menuUpdateDto.getParentId() != 0L){
                MenuPo parentPo = this.getById(menuUpdateDto.getParentId());
                String menuType = parentPo.getMenuType();
                if (!menuType.equals("M")){
                    throw new BaseException("选择的上级不是目录");
                }
            }
        }
        BeanUtil.copyProperties(menuUpdateDto,menuPo);
        this.updateById(menuPo);
    }

    @Override
    public MenuVo getMenuById(Long menuId){
        MenuPo menuPo = this.getById(menuId);
        return this.toMenuVo(menuPo);
    }

    private MenuVo toMenuVo(MenuPo menuPo){
        MenuVo vo = new MenuVo();
        vo.setId(menuPo.getId());
        vo.setMenuName(menuPo.getMenuName());
        vo.setMenuType(menuPo.getMenuType());
        vo.setIcon(menuPo.getIcon());
        vo.setUrl(menuPo.getUrl());
        vo.setParentId(menuPo.getParentId());
        vo.setShortCode(menuPo.getShortCode());
        vo.setMenuCode(menuPo.getMenuCode());
        vo.setCreateTime(menuPo.getCreateTime());
        return vo;
    }

    /**
     * 删除菜单
     * @param menuId
     */
    @Override
    public void deleteMenu(Long menuId){
        // 查询是否存在
        MenuPo menuPo = this.getById(menuId);
        if (ObjectUtil.isEmpty(menuPo)){
            throw new BaseException("删除的菜单不存在");
        }
        this.removeById(menuId);
    }

    @Override
    public List<RouteVo> queryRoutesTree() {
        List<MenuTreeVo> menuTreeVos = this.queryMenuTree(null);
        if (ObjectUtil.isNotEmpty(menuTreeVos)){
            List<RouteVo> routeVos = new ArrayList<>();
            TreeUtil.forEach(menuTreeVos,(menuTreeVo, parent, index) -> {
                if (ObjectUtil.equal("HOME",menuTreeVo.getMenuCode())){
                    return;
                }
                RouteVo routeVo = new RouteVo();
                routeVo.setId(menuTreeVo.getId());
                routeVo.setParentId(menuTreeVo.getParentId());
                routeVo.setName(menuTreeVo.getMenuCode());
                routeVo.setPath(menuTreeVo.getUrl());
                if (ObjectUtil.isEmpty(menuTreeVo.getComponent())){
                    menuTreeVo.setComponent("Layout");
                }
                routeVo.setComponent(menuTreeVo.getComponent());
                routeVo.setHidden(menuTreeVo.getHidden()!=null && menuTreeVo.getHidden()!=0);
                routeVo.setMetaTitle(menuTreeVo.getMenuName()).setIcon(menuTreeVo.getIcon());
                routeVos.add(routeVo);
            });
            return TreeUtil.buildTree(routeVos, 0L);
        }
        return null;
    }

    @Override
    public List<MenuTreeVo> getParentMenu(MenuSearchDto searchForm) {
        List<MenuTreeVo> treeVos = new ArrayList<>( );
        List<MenuPo> menuPos = this.getLambadaQueryWrapper().eq(MenuPo::getMenuType,"module").list();
        if (menuPos != null){
            for (MenuPo menuPo : menuPos) {
                MenuTreeVo treeVo = new MenuTreeVo();
                BeanUtils.copyProperties(menuPo,treeVo);
                treeVos.add(treeVo);
            }
            treeVos = TreeUtil.buildTree(treeVos, 0L);
        }
        return treeVos;
    }
}
